home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # GDeviceUtils.cp
- #
- # by Eric Traut
- #
- ------------------------------------------------------------------------------*/
-
- #include "GDeviceUtils.h"
-
- #include <Memory.h>
- #include <LowMem.h>
- #include <Displays.h>
- #include <Traps.h>
-
-
-
- /*---------------------------------------------------------------
- GraphicSurface
- ---------------------------------------------------------------*/
-
- GraphicSurface::GraphicSurface()
- {
- // Nothing to do
- mPixelData = NULL;
- }
-
-
- /*---------------------------------------------------------------
- ExtractRealDeviceInfo
- ---------------------------------------------------------------*/
-
- void
- GraphicSurface::ExtractRealDeviceInfo(
- GDHandle inGDevice)
- {
- PixMapHandle pixMap;
-
- pixMap = inGDevice[0]->gdPMap;
-
- mRowBytes = pixMap[0]->rowBytes & 0x3FFF;
- mPixelData = (UInt8 *)pixMap[0]->baseAddr;
- mBitDepth = pixMap[0]->pixelSize;
- mHeight = pixMap[0]->bounds.bottom - pixMap[0]->bounds.top;
- mWidth = pixMap[0]->bounds.right - pixMap[0]->bounds.left;
- }
-
-
- /*---------------------------------------------------------------
- CapturedGDevice
- ---------------------------------------------------------------*/
-
- CapturedGDevice::CapturedGDevice()
- {
- mGDHandle = NULL;
- mDeviceCaptured = false;
-
- mVirtualDeviceList = NULL;
- mVirtualDeviceCount = 0;
-
- mBlendEffect = NULL;
- }
-
-
- /*---------------------------------------------------------------
- ~CapturedGDevice
- ---------------------------------------------------------------*/
-
- CapturedGDevice::~CapturedGDevice()
- {
- if (mDeviceCaptured)
- UncaptureDevice();
- }
-
-
- /*---------------------------------------------------------------
- CaptureDevice
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::CaptureDevice(
- GDHandle inGDevice,
- VirtualGDevice ** inVDeviceList,
- UInt32 inVDeviceCount)
- {
- HideCursor();
- if (mDeviceCaptured)
- UncaptureDevice();
-
- mGDHandle = inGDevice;
-
- OSErr err = ::DMGetDisplayIDByGDevice(inGDevice, &mDisplayID, false);
- if (err != noErr)
- DebugStr("\pCouldn't get DisplayID");
-
- mCapturedSurface.ExtractRealDeviceInfo(mGDHandle);
-
- // For now, we only support 16-bit mode.
- if (mCapturedSurface.GetBitDepth() != 16)
- {
- // fix me - report an error
- }
- else
- {
- mVirtualDeviceList = inVDeviceList;
- mVirtualDeviceCount = inVDeviceCount;
-
- // Tell each of the virtual monitors to initialize
- // itself. Initialize in reverse order because
- // the display manager orders them that way.
- for (SInt32 vDeviceIndex = inVDeviceCount - 1; vDeviceIndex >= 0; vDeviceIndex--)
- inVDeviceList[vDeviceIndex]->Initialize(*this, vDeviceIndex);
-
- err = ::DMSetMainDisplay(inVDeviceList[0]->GetGDHandle(), NULL);
- if (err != noErr)
- DebugStr("\p Error SetMainDisplay");
- RecomputeGDHandle();
-
- // We need to recompute the GDHandles from the display IDs
- // because they may have been rearranged.
- for (UInt32 vDeviceIndex = 0; vDeviceIndex < inVDeviceCount; vDeviceIndex++)
- inVDeviceList[vDeviceIndex]->RecomputeGDHandle();
-
- // Now position the displays (Can't move main display)
- for (SInt32 vDeviceIndex = 1; vDeviceIndex < inVDeviceCount; vDeviceIndex++)
- {
- Rect newPos;
- inVDeviceList[vDeviceIndex]->GetPreferredPosition(newPos);
- err = ::DMMoveDisplay(inVDeviceList[vDeviceIndex]->GetGDHandle(), newPos.left, newPos.top, NULL);
- if (err != noErr)
- DebugStr("\pMoveDisplay failed");
- }
-
- // Now get rid of the rounded area in the corners
- RgnHandle rgn = NewRgn();
- RgnHandle grayRgn = LMGetGrayRgn();
- for (SInt32 vDeviceIndex = 0; vDeviceIndex < inVDeviceCount; vDeviceIndex++) {
- GDHandle gdHandle = inVDeviceList[vDeviceIndex]->GetGDHandle();
- SetDeviceAttribute(gdHandle, roundedDevice, false);
-
- Rect r = (**gdHandle).gdRect;
- if (r.left == 0 && r.top == 0) r.top = GetMBarHeight();
- RectRgn(rgn, &r);
- MacUnionRgn(grayRgn, rgn, grayRgn);
- }
- DisposeRgn(rgn);
-
- CWindowRecord wr;
- CWindowPtr wp = (CWindowPtr)NewCWindow(&wr, &(**LMGetGrayRgn()).rgnBBox, "\p ", true, plainDBox, 0, false, 237);
- CloseWindow((WindowPtr)wp);
-
- mDeviceCaptured = true;
- }
- ShowCursor();
- }
-
-
- /*---------------------------------------------------------------
- UncaptureDevice
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::UncaptureDevice()
- {
- if (mDeviceCaptured)
- {
- RecomputeGDHandle();
- OSErr err = ::DMSetMainDisplay(mGDHandle, NULL);
- if (err != noErr)
- DebugStr("\p Error SetMainDisplay");
- RecomputeGDHandle();
-
- // Tell each of the virtual monitors to
- // uninitialize itself.
- for (UInt32 vDeviceIndex = 0; vDeviceIndex < mVirtualDeviceCount; vDeviceIndex++)
- {
- if (mVirtualDeviceList[vDeviceIndex] != NULL)
- mVirtualDeviceList[vDeviceIndex]->Uninitialize();
- }
-
- mDeviceCaptured = false;
- }
- }
-
-
- /*---------------------------------------------------------------
- UncaptureDevice
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::SetPixelBase(
- UInt8 * inPixelBase)
- {
- PixMapHandle pixMap;
-
- RecomputeGDHandle();
- if (mGDHandle != NULL)
- {
- pixMap = mGDHandle[0]->gdPMap;
- pixMap[0]->baseAddr = (Ptr)inPixelBase;
- }
- }
-
-
- /*---------------------------------------------------------------
- UpdateCapturedScreen
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::UpdateCapturedScreen()
- {
- if (mBlendEffect != NULL)
- {
- mBlendEffect->BlendVirtualDevices(
- mCapturedSurface,
- mVirtualDeviceList,
- mVirtualDeviceCount);
- }
- }
-
-
- /*---------------------------------------------------------------
- RecomputeGDHandle
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::RecomputeGDHandle()
- {
- OSErr err;
-
- err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
-
- if (err != noErr)
- {
- DebugStr("\pFailedToFindDevice");
- mGDHandle = NULL;
- }
- }
-
-
- /*---------------------------------------------------------------
- SetGraphicBlendEffect
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::SetGraphicBlendEffect(
- GraphicBlendEffect * inBlendEffect)
- {
- if (mBlendEffect != NULL)
- {
- GraphicBlendEffect * tempEffect = mBlendEffect;
-
- // Set it to NULL first so time manager
- // task doesn't call the effect after it's
- // deallocated.
- mBlendEffect = NULL;
- delete tempEffect;
- }
-
- // We need to wipe the dest screen to black
- ClearCapturedScreen();
-
- mBlendEffect = inBlendEffect;
- }
-
-
- /*---------------------------------------------------------------
- SetGraphicBlendValue
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::SetGraphicBlendValue(
- UInt32 inValueIndex,
- double inValue)
- {
- if (mBlendEffect != NULL)
- {
- mBlendEffect->SetEffectValue(inValueIndex, inValue);
- }
- }
-
-
- /*---------------------------------------------------------------
- ClearCapturedScreen
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::ClearCapturedScreen()
- {
- // The simple blend effect simply involves
- // copying the pixels from the first virtual
- // device to the destination surface.
- UInt32 totalRows = mCapturedSurface.GetHeight();
- UInt32 totalCols = mCapturedSurface.GetWidth();
- UInt8 * destPtr;
-
- for (UInt32 row = 0; row < totalRows; row++)
- {
- destPtr = mCapturedSurface.GetPixelDataPtr() + mCapturedSurface.GetRowBytes() * row;
-
- for (UInt32 col = 0; col < totalCols; col++)
- {
- *(UInt16 *)destPtr = 0;
- destPtr += 2;
- }
- }
- }
-
-
- /*---------------------------------------------------------------
- VirtualGDevice
- ---------------------------------------------------------------*/
-
- VirtualGDevice::VirtualGDevice()
- {
- mDeviceBacking = NULL;
- mGDHandle = NULL;
- mAddedToDeviceList = false;
- }
-
-
- /*---------------------------------------------------------------
- ~VirtualGDevice
- ---------------------------------------------------------------*/
-
- VirtualGDevice::~VirtualGDevice()
- {
- Uninitialize();
- }
-
-
- /*---------------------------------------------------------------
- Initialize
- ---------------------------------------------------------------*/
-
- Boolean
- VirtualGDevice::Initialize(
- CapturedGDevice & inRealGDevice,
- UInt32 inIndex)
- {
- // Allocate backing memory for the virtual device
- Ptr backingPtr;
- backingPtr = ::NewPtrClear(inRealGDevice.GetGraphicSurface().GetBackingSize());
-
- if (backingPtr == NULL)
- return false;
-
- mDeviceBacking = backingPtr;
-
- // Allocate a new GDevice if this isn't the primary
- // virtual device.
-
- // fix me - what is the first parameter?
- mGDHandle = ::NewGDevice(0, -1);
- if (mGDHandle == NULL)
- return false;
- ::HLock((Handle)mGDHandle);
-
- Handle itableHandle;
-
- itableHandle = ::NewHandle(0);
- if (itableHandle == NULL)
- return false;
-
- // Make a default inverse table
- ::MakeITable(NULL, (ITabHandle)itableHandle, 4);
-
- mGDHandle[0]->gdRefNum = 0;
- mGDHandle[0]->gdID = 1024 + inIndex;
- mGDHandle[0]->gdType = 2;
- mGDHandle[0]->gdITable = (ITabHandle)itableHandle;
- mGDHandle[0]->gdFlags = (1L << gdDevType) | // Color device
- (1L << noDriver) | // No driver
- (1L << screenDevice) | // It's a screen device (not printer)
- (1L << screenActive) | // It's active
- (1L << burstDevice) |
- (1L << allInit);
- mGDHandle[0]->gdMode = 129;
-
- // Set up the device rectangle
- mGDHandle[0]->gdRect.left = (inIndex % 2) * inRealGDevice.GetGraphicSurface().GetWidth();
- mGDHandle[0]->gdRect.top = (inIndex / 2) * inRealGDevice.GetGraphicSurface().GetHeight();
- mGDHandle[0]->gdRect.right = mGDHandle[0]->gdRect.left + inRealGDevice.GetGraphicSurface().GetWidth();
- mGDHandle[0]->gdRect.bottom = mGDHandle[0]->gdRect.top + inRealGDevice.GetGraphicSurface().GetHeight();
-
- mPreferredPos = mGDHandle[0]->gdRect;
-
- // Now, set up the pix map for the gdevice
- PixMapHandle realPixMap = inRealGDevice.GetPixMapHandle();
- PixMapHandle virtPixMap = mGDHandle[0]->gdPMap;
-
- // Copy the pix map info
- virtPixMap[0]->baseAddr = mDeviceBacking;
- virtPixMap[0]->rowBytes = realPixMap[0]->rowBytes;
- virtPixMap[0]->bounds = realPixMap[0]->bounds;
- virtPixMap[0]->pmVersion = realPixMap[0]->pmVersion;
- virtPixMap[0]->packType = realPixMap[0]->packType;
- virtPixMap[0]->packSize = realPixMap[0]->packSize;
- virtPixMap[0]->hRes = realPixMap[0]->hRes;
- virtPixMap[0]->vRes = realPixMap[0]->vRes;
- virtPixMap[0]->pixelType = realPixMap[0]->pixelType;
- virtPixMap[0]->pixelSize = realPixMap[0]->pixelSize;
- virtPixMap[0]->cmpCount = realPixMap[0]->cmpCount;
- virtPixMap[0]->cmpSize = realPixMap[0]->cmpSize;
- virtPixMap[0]->planeBytes = realPixMap[0]->planeBytes;
- virtPixMap[0]->pmReserved = realPixMap[0]->pmReserved;
-
- if (virtPixMap[0]->pmTable != NULL)
- virtPixMap[0]->pmTable[0]->ctFlags = 0x8000;
-
- DMAddDisplay(
- mGDHandle,
- mGDHandle[0]->gdRefNum,
- mGDHandle[0]->gdMode,
- 0,
- 0,
- NULL,
- NULL);
-
- DMEnableDisplay(mGDHandle, NULL);
-
- OSErr err = ::DMGetDisplayIDByGDevice(mGDHandle, &mDisplayID, false);
- if (err != noErr)
- DebugStr("\pCouldn't get DisplayID");
-
- mAddedToDeviceList = true;
-
- mVirtualSurface.ExtractRealDeviceInfo(mGDHandle);
-
- return true;
- }
-
-
- /*---------------------------------------------------------------
- Uninitialize
- ---------------------------------------------------------------*/
-
- void
- VirtualGDevice::Uninitialize()
- {
- if (mDeviceBacking != NULL)
- {
- if (mAddedToDeviceList)
- {
- RecomputeGDHandle();
- ::DMRemoveDisplay(mGDHandle, NULL);
- mAddedToDeviceList = false;
- }
-
- if (mGDHandle != NULL)
- ::DisposeGDevice(mGDHandle);
- mGDHandle = NULL;
-
- ::DisposePtr(mDeviceBacking);
- mDeviceBacking = NULL;
- }
- }
-
-
- /*---------------------------------------------------------------
- RecomputeGDHandle
- ---------------------------------------------------------------*/
-
- void
- VirtualGDevice::RecomputeGDHandle()
- {
- OSErr err;
-
- err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
-
- if (err != noErr)
- {
- DebugStr("\pFailedToFindDevice");
- mGDHandle = NULL;
- }
- else
- {
- // Reset the backing address. It seems
- // to get reset when we set the main device.
- mGDHandle[0]->gdPMap[0]->baseAddr = mDeviceBacking;
- }
- }
-